相关的介绍
描述
LCA问题,即Least Common Ancestors,最近公共祖先问题,给定一棵树T再给出一些查询LCA(u,v)(当查询量较大的时候),每次查询的都是u和v的祖先,并且让所查询的点的深度尽可能的深。
解决LCA问题的方法
线段树,Tarjan,RMQ,倍增
LCA问题的形式
给定一棵树,并给出若干个查询每个查询要求指定节点u和v的最近公共祖先
解决思路
·在线算法:对每个查询进行处理给出答案
·离线算法:进行与处理之后对于每一个查询给出答案
算法思路
Tarjan离线算法是基于DFS和并查集的一种算法,算法从根节点开始每次递归搜索所有的子树,再处理当前根节点相关的所有查询。
每当搜索到点n的时候,就创建一个关于该点的集合,这个集合的先祖就是n自己,接下来递归搜素n的所有的子树,每搜索完一个子树的时候就把该子树的集合与n集合相连接起来,并且把这个合并之后的集合的先祖设为n,因为这棵子树内的已经查询完毕了,n的其他子树节点跟这颗的LCA都是一样的,都为当前节点x。所有的子树处理完毕之后处理当前根节点n的查询。遍历n的所有查询,如果所查询的另外一个点已经遍历过了,那么n和v的LCA即为v所在的集合的祖先。
总结
从最底层开始往上遍历合并子树,直到两个查询的节点都已经被标记过了,那么当前位置所在的根即为我们所要寻找的LCA(u,v)
代码
1 | typedef int mytype; |
友情链接
http://noalgo.info/476.html
https://github.com/fz568573448/ACM-ICPC-Template/blob/master/%E6%A8%A1%E6%9D%BF/8_%E5%9B%BE%E8%AE%BA/13_LCA%E7%9A%84tarjan%E7%A6%BB%E7%BA%BF%E7%AE%97%E6%B3%95.cpp